﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Sofire.Data.XSql;

namespace Sofire.Data
{
    /// <summary>
    /// 基于查询上下文的 XSql 查询管理器。
    /// </summary>
    /// <typeparam name="TModel">实体的类型。</typeparam>
    public class DbContext<TModel> : IDisposable where TModel : class ,IModelLoadable, new()
    {
        private QueryContext _Context;
        /// <summary>
        /// 获取查询上下文。
        /// </summary>
        public QueryContext Context
        {
            get
            {
                return this._Context;
            }
        }

        private IXSqlDocument _Document;
        /// <summary>
        /// 获取实体类型的 <see cref="Sofire.Data.XSql.IXSqlDocument"/> 实例。
        /// </summary>
        public IXSqlDocument Document
        {
            get
            {
                return _Document;
            }
        }

        /// <summary>
        /// 初始化 <see cref="Sofire.Data.DbContext&lt;TModel&gt;"/> 的新实例。
        /// </summary>
        /// <param name="document">实体类型的 <see cref="Sofire.Data.XSql.IXSqlDocument"/> 实例。</param>
        public DbContext(IXSqlDocument document)
            : this(document, document == null ? null : document.Engine.Context) { }

        /// <summary>
        /// 初始化 <see cref="Sofire.Data.DbContext&lt;TModel&gt;"/> 的新实例。
        /// </summary>
        /// <param name="document">实体类型的 <see cref="Sofire.Data.XSql.IXSqlDocument"/> 实例。</param>
        /// <param name="queryContext">查询上下文。</param>
        public DbContext(IXSqlDocument document, QueryContext queryContext)
        {
            this._Document = document;
            this._Context = queryContext;
        }

        /// <summary>
        /// 执行查询，并返回自定义只读实体的集合。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public Result<List<TModel>> ExecuteModels(string name, XSqlParameterCollection parameters = null)
        {
            return _Context.ExecuteModels<TModel>(_Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并返回自定义只读实体的集合。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public Result<TModel> ExecuteModel(string name, XSqlParameterCollection parameters = null)
        {
            return _Context.ExecuteModel<TModel>(_Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并返回查询结果集中第一行的第一列。忽略额外的列或行。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public ScalarResult ExecuteScalar(string name, XSqlParameterCollection parameters = null)
        {
            return _Context.ExecuteScalar(_Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并返回受影响的行数。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public NonQueryResult ExecuteNonQuery(string name, XSqlParameterCollection parameters = null)
        {
            return _Context.ExecuteNonQuery(_Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并返回一个数据表。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public TableResult ExecuteTable(string name, XSqlParameterCollection parameters = null)
        {
            return _Context.ExecuteTable(_Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并返回一个数据集。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public DataSetResult ExecuteDataSet(string name, XSqlParameterCollection parameters = null)
        {
            return _Context.ExecuteDataSet(_Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并完成一个事务。
        /// </summary>
        /// <param name="args">事务参数集合。</param>
        public MultiNonQueryResult ExecuteTransaction(IEnumerable<TransactionArgument> args)
        {
            List<ExecuteCommand> commands = new List<ExecuteCommand>();
            foreach(var arg in args)
            {
                commands.Add(_Document.CreateCommand(arg.Name, arg.Parameters));
            }

            return _Context.ExecuteTransaction(commands);
        }

        /// <summary>
        /// 执行查询，并完成一个事务。
        /// </summary>
        /// <param name="args">事务参数集合。</param>
        public MultiNonQueryResult ExecuteTransaction(params TransactionArgument[] args)
        {
            return ExecuteTransaction((IEnumerable<TransactionArgument>)args);
        }

        #region IDisposable 成员

        void IDisposable.Dispose()
        {
            this._Context.Close();
        }

        /// <summary>
        /// 析构函数。
        /// </summary>
        ~DbContext()
        {
            this._Context.Close();
        }

        #endregion
    }

    /// <summary>
    /// 基于查询引擎的 XSql 查询管理器。
    /// </summary>
    /// <typeparam name="TModel">实体的类型。</typeparam>
    public class Db<TModel> where TModel : class ,IModelLoadable, new()
    {
        private static readonly object SyncObject = new object();

        internal bool HasDocument
        {
            get
            {
                return _Document != null;
            }
        }
        private static IXSqlDocument _Document;
        /// <summary>
        /// 设置或获取当前实体类型的 <see cref="Sofire.Data.XSql.IXSqlDocument"/> 实例。
        /// </summary>
        public static IXSqlDocument Document
        {
            get
            {
                if(_Document == null)
                {
                    lock(SyncObject)
                    {
                        if(_Document == null)
                        {
                            XSqlManager.Find<TModel>();
                            //var type = typeof(TModel);
                            //var path = XSqlPackage.Get(type);
                            //if(path == null) return null;
                            //_Document = XSqlManager.Register(My.Engine, type, path);
                        }
                    }
                }
                return _Document;
            }
            set
            {
                if(_Document != value)
                {
                    lock(SyncObject)
                    {
                        if(_Document != value) _Document = value;
                    }
                }
            }
        }

        /// <summary>
        /// 创建并返回一个基于查询上下文的 XSql 查询管理器。
        /// </summary>
        public static DbContext<TModel> Context
        {
            get
            {
                return new DbContext<TModel>(Document);
            }
        }

        /// <summary>
        /// 执行查询，并返回自定义只读实体的集合。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public static Result<List<TModel>> ExecuteModels(string name, XSqlParameterCollection parameters = null)
        {
            return My.Engine.ExecuteModels<TModel>(Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并返回自定义只读实体的集合。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public static Result<TModel> ExecuteModel(string name, XSqlParameterCollection parameters = null)
        {
            return My.Engine.ExecuteModel<TModel>(Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并返回查询结果集中第一行的第一列。忽略额外的列或行。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public static ScalarResult ExecuteScalar(string name, XSqlParameterCollection parameters = null)
        {
            return My.Engine.ExecuteScalar(Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并返回受影响的行数。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public static NonQueryResult ExecuteNonQuery(string name, XSqlParameterCollection parameters = null)
        {
            return My.Engine.ExecuteNonQuery(Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并返回一个数据表。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public static TableResult ExecuteTable(string name, XSqlParameterCollection parameters = null)
        {
            return My.Engine.ExecuteTable(Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并返回一个数据集。
        /// </summary>
        /// <param name="name">XSql 名称。</param>
        /// <param name="parameters">参数集合。</param>
        public static DataSetResult ExecuteDataSet(string name, XSqlParameterCollection parameters = null)
        {
            return My.Engine.ExecuteDataSet(Document.CreateCommand(name, parameters));
        }

        /// <summary>
        /// 执行查询，并完成一个事务。
        /// </summary>
        /// <param name="args">事务参数集合。</param>
        public static MultiNonQueryResult ExecuteTransaction(IEnumerable<TransactionArgument> args)
        {
            List<ExecuteCommand> commands = new List<ExecuteCommand>();
            foreach(var arg in args)
            {
                commands.Add(Document.CreateCommand(arg.Name, arg.Parameters));
            }

            return My.Engine.ExecuteTransaction(commands);
        }

        /// <summary>
        /// 执行查询，并完成一个事务。
        /// </summary>
        /// <param name="args">事务参数集合。</param>
        public static MultiNonQueryResult ExecuteTransaction(params TransactionArgument[] args)
        {
            return ExecuteTransaction((IEnumerable<TransactionArgument>)args);
        }
    }

    /// <summary>
    /// 执行事务查询时的参数。
    /// </summary>
    public class TransactionArgument
    {
        private string _Name;
        /// <summary>
        /// 设置或获取 XSql 的名称。
        /// </summary>
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        private XSqlParameterCollection _Parameters;
        /// <summary>
        /// 获取 XSql 的参数集合。
        /// </summary>
        public XSqlParameterCollection Parameters
        {
            get
            {
                if(_Parameters == null)
                {
                    _Parameters = new XSqlParameterCollection();
                }
                return _Parameters;
            }
        }

        /// <summary>
        /// 初始化 <see cref="Sofire.Data.TransactionArgument"/> 的新实例。
        /// </summary>
        public TransactionArgument() { }

        /// <summary>
        /// 初始化 <see cref="Sofire.Data.TransactionArgument"/> 的新实例。
        /// </summary>
        /// <param name="name">XSql 的名称。</param>
        /// <param name="parameters">XSql 的参数集合。</param>
        public TransactionArgument(string name, XSqlParameterCollection parameters)
        {
            this._Name = name;
            this._Parameters = parameters;
        }
    }
}
